package com.hushan.elevator.service.impl;

import com.hushan.elevator.dao.DepartmentRepository;
import com.hushan.elevator.model.Department;
import com.hushan.elevator.model.User;
import com.hushan.elevator.security.SecurityUtils;
import com.hushan.elevator.service.DeptService;
import com.hushan.elevator.service.UserService;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;



@Service
public class DeptServiceImpl implements DeptService {

    private final DepartmentRepository deptDao;
    private final UserService userService;
    @Autowired
    public DeptServiceImpl(DepartmentRepository deptDao, UserService userService) {
        this.deptDao = deptDao;
        this.userService = userService;
    }


    @Override
    public Department findDeptById(Integer id) {
        return deptDao.findById(id).orElse(null);
    }

    @Override
    @Transactional
    public void saveDepartment(Department department) {
        deptDao.save(department);
    }

    @Override
    public long findDeptCount(Department department) {
        Example<Department> example = Example.of(department);
        return deptDao.count(example);
    }

    @Override
    public int findChildrenDeptCount(int deptId) {
        return deptDao.findChildCountByDeptId(deptId);
    }

    @Override
    @Transactional
    public void deleteDepartment(Department department) {
        List<Department> deletedDepts = findChildByDeptId(department.getDeptId());
        deletedDepts.add(department);
        deletedDepts.forEach(item -> item.setIsDeleted(true));
        for (Department dept : deletedDepts) {
            List<User> usersByDept = userService.findUsersByDept(dept.getDeptId());
            userService.deleteUsers(usersByDept);
        }
        deptDao.saveAll(deletedDepts);
    }

    @Override
    public Department findDeptByUserId(int userId) {
        return deptDao.findUserDept(userId);
    }

    @Override
    public List<Department> findDeptByParentId(Integer parentId) {
        Department example = new Department();
        example.setParentId(parentId);
        Example<Department> e = Example.of(example);

        return deptDao.findAll(e);
    }

    @Override
    public boolean detectDeptAuth(String ancestors, int s) {
        boolean hasPermission;
        try {
            // split the ancestors
            String[] parents = ancestors.split(",");
            List<String> parentsList = new ArrayList<>(Arrays.asList(parents));
            hasPermission = parentsList.contains(String.valueOf(s));
        } catch (Exception e) {
            throw new RuntimeException("authority error");
        }
        return hasPermission;
    }

    @Override
    public List<Department> findChildByDeptId(Integer deptId) {
        return deptDao.findChildByDeptId(deptId);
    }

    @Override
    public boolean findIsAncestors(Department parent, Department son) {
        String[] actualParents = son.getAncestors().split(",");
        List<String> actualParentList = new ArrayList<>(Arrays.asList(actualParents));
        // detect authority, is the requested dept ancestors has request initiator dept
        return actualParentList.contains(String.valueOf(parent.getDeptId()));
    }

    @Override
    public boolean findUserPermissionForDept(User user, Department dept) {
        // requester dept
        User requestUser = SecurityUtils.getUser();
        Department requesterDept = deptDao.findUserDept(requestUser.getUserId());
        if (Objects.equals(requesterDept.getDeptId(), dept.getDeptId())) {
            return true;
        }
        // be requested dept ancestors
        String ancestors = dept.getAncestors();
        return detectDeptAuth(ancestors, requesterDept.getDeptId());
    }

    @Override
    public boolean findUserPermissionForDept(User user, int deptId) {
        // requester dept
        User requestUser = SecurityUtils.getUser();
        Department dept = findDeptById(deptId);
        findUserPermissionForDept(requestUser,dept);
        return findUserPermissionForDept(requestUser,dept);
    }
}
